package com;

import com.inbound.ClientDisconnectHandler;
import com.inbound.IdleStateProcessHandler;
import com.inbound.ProtocolDispatcherHandler;
import com.inbound.RegisterHandler;
import com.object.Gprs;
import com.object.OtaObject;
import com.object.OtaTarget;
import com.outbound.ProtocolCompleteOutboundHandler;
import com.sql.SqlOperation;
import com.sql.SqlThread;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.CompleteFrameHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.AttributeKey;

import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import org.junit.experimental.theories.Theories;

public class NettyServer {
    private String ip;
    private int port;

    public final static AttributeKey<Gprs> GPRS = AttributeKey.valueOf("GPRS");
    public final static ConcurrentHashMap<String, Gprs> GPRS_MAP = new ConcurrentHashMap<>();
    public final static ConcurrentHashMap<String, OtaService> GPRS_OTASERVICE = new ConcurrentHashMap<>();
    public static int PORT;
   // public static int UNPACK_FRAME_LENGTH;

    public NettyServer(String ip, int port){
        this.ip = ip;
        this.port = port;
    }

    public static void main(String[] args) throws Exception{
        //String ip = "114.55.114.201";
        //String ip = "172.31.118.198";
    	String ip="172.19.160.193";
        // 所有设备都离线
        SqlOperation.resetAllGprsStatus();
        //String ip = "localhost";
        int port = 9000;
//        if (args.length == 1)
//            port = Integer.parseInt(args[0]);
//        else if (args.length == 2){
//            ip = args[0];
//            port = Integer.parseInt(args[1]);
//        }
        if(args.length==1) {
        	OtaService.UNPACK_FRAME_LENGTH=Integer.parseInt(args[0]);
        	OtaService.DATA_FRAME_LENGTH= OtaService.UNPACK_FRAME_LENGTH - OtaService.HEADER_TAIL_LENGTH; // 数据段中包含升级程序的长度
        	OtaService.FRAME_LENGTH = OtaService.UNPACK_FRAME_LENGTH + 3;
        	OtaService.UPGRADE_SLAVE_LENGTH = OtaService.UPGRADE_HOST_LENGTH + 3;
        	//UNPACK_FRAME_LENGTH=Integer.parseInt(args[0]);
        	System.out.println("数据长度为:"+OtaService.UNPACK_FRAME_LENGTH);
        	
        }
        PORT = port;
        new NettyServer(ip, port).start();
        SqlThread sqlThread = new SqlThread();
        new Thread(sqlThread).start();

    }

    private static  void cmdProcesser(String[] args)throws Exception{
        System.out.println("Waiting Input");
        Scanner in = new Scanner(System.in);
        while (in.hasNextLine()) {
            String gprsid = in.nextLine();
            Gprs gprs = GPRS_MAP.get(gprsid);
            if (gprs == null && gprsid !="")
                System.out.println(gprsid + " doesn't exist");
            else{
                OtaObject ob = new OtaObject();
                ob.otaTarget = OtaTarget.STM_HOST;
                ob.binFilePath = "C:\\Users\\PuliTech\\Documents\\GeorgeCaoJ\\GPRS后台接收客户端\\docs\\base_master_BLE.bin";
                ob.firmware = 31;
                ob.version = 31;
                gprs.fireOtaService(ob);
            }
        }
    }

    public void start() throws  Exception{
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1000)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    .childHandler(new ChannelInitializer<SocketChannel>(){
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception{
                            ChannelPipeline p =ch.pipeline();

                            // outbound must add fisrt
                            // outbound
                            p.addLast("Protocol Complete", new ProtocolCompleteOutboundHandler());


                            // inbound
                            p.addLast(new IdleStateHandler(30, 30, 30, TimeUnit.MINUTES)); // 30 分钟的读写空闲触发空闲连接时间
                            p.addLast(new IdleStateProcessHandler());
                            p.addLast("Complete Frame",new CompleteFrameHandler());
                            p.addLast("Register", new RegisterHandler());
                            p.addLast("Protocol Dispatcher", new ProtocolDispatcherHandler());
                            p.addLast("Client Disconnect", new ClientDisconnectHandler());


                        }
                    });
            ChannelFuture f = b.bind(ip, port).sync();
            System.out.println(ip + ":" + port + " is on");
//            f.channel().closeFuture().sync();
        }
        finally{
//            bossGroup.shutdownGracefully();
//            workerGroup.shutdownGracefully();
        }
    }
}
